home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
028a
/
sq0928.zip
/
XUSQ.C
< prev
Wrap
C/C++ Source or Header
|
1990-09-13
|
9KB
|
420 lines
/*% cc -M2 -compat -O -K -i % -o usq
<-xtx-*> cc -O -K -dos xusq.c /usr/lib/dos/rawmode.o -o usq.exe; ls -l usq.exe
*
* usq.c - CP/M compatible file unsqueezer utility
* **** N.B.: short int must be 16 bits ****
*/
static char *sccsid = "@(#)usq.c 2.17 (CAF) 09-12-90";
#ifdef vax11c /* we only want 16 bit integers */
#include <types.h>
#include <stat.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#else
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <ctype.h>
#endif
#define TRUE 1
#define FALSE 0
#define ERROR (-1)
#define PATHLEN 312 /* Number of characters allowed in pathname */
#define OK 0
/* Special hacks for BBN C70 with high tech 20 bit integers */
#ifdef C70
#define POSITIVE(i) (i < 0x8000)
#define NEG16TOINT(i) (i |= 0xF000;)
#else
#define POSITIVE(i) (i >= 0)
#define NEG16TOINT(i)
#endif
#define SQMAGIC 0xFF76 /* SQueezed file prefix */
#define KSQMAGIC 0xFF75 /* Cipher key magic word */
#define KEYSIZE 4096 /* Max size of key file */
unsigned char Keybuf[KEYSIZE];
char Keyname[PATHLEN];
int Key;
#define DLE 0x90 /* repeat byte flag */
#define SPEOF 256 /* special endfile token */
#define NUMVALS 257 /* 256 data values plus SPEOF*/
#define LARGE 30000
struct _sqleaf { /* Decoding tree */
short int _children[2]; /* left, right */
};
struct _sqleaf Dnode[NUMVALS - 1];
int Bpos; /* last bit position read */
int Repct; /* Number of times to return value */
int MakeLCPathname=TRUE; /* translate pathname to lc if all caps */
int Nlmode=FALSE; /* zap cr's if true */
int Fullpathname = FALSE; /* use full pathname */
int inbackground = 0;
int Verbose = FALSE;
FILE *in, *out;
unsigned char *Keyptr;
unsigned char *Keyend;
char *stem();
main(argc, argv)
char *argv[];
{
register char *cp;
register int npats;
char **patts;
int n, errorstat;
if (signal(SIGINT, SIG_IGN)==SIG_IGN)
inbackground++;
else
signal(SIGINT, SIG_DFL);
#ifdef SIGHUP
signal(SIGHUP, SIG_IGN);
#endif
npats=0; errorstat=0; out = 0;
if (argc<2)
goto usage;
while (--argc) {
cp = *++argv;
if (*cp == '-' && cp[1]) {
while ( *++cp) {
switch(*cp) {
case 'f':
case 'F':
Fullpathname = TRUE; break;
case 'l':
case 'L':
out = stdout; break;
case 'n':
case 'N':
Nlmode=TRUE; break;
case 'u':
case 'U':
MakeLCPathname=FALSE; break;
case 'v':
case 'V':
Verbose=TRUE; break;
default:
goto usage;
}
}
}
else if ( !npats && argc>0) {
if (argv[0][0]) {
npats=argc;
patts=argv;
}
}
}
if (npats < 1) {
usage:
fprintf(stderr,"%s\n\nUsage: usq [-flnuv] [-] file ...\n",sccsid);
fprintf(stderr,"\t-f use Full pathname\n");
fprintf(stderr,"\t-l List file(s) to stdout\n");
fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
fprintf(stderr,"\t-u preserve Uppercase names\n");
fprintf(stderr,"\t-v Verbose\n");
#ifdef vax11c
return;
#else
exit(1);
#endif
}
for (n=0; n<npats; ++n)
errorstat |= usqueeze(patts[n]);
#ifdef vax11c
return;
#else
exit(errorstat != 0);
#endif
}
/*
* Following code modified from USQ by Dick Greenlaw.
*/
usqueeze(fname)
char *fname;
{
register int i, c;
register int numnodes; /* size of decoding tree */
register unsigned int crc;
unsigned filecrc;
register char *p;
char origname[PATHLEN]; /* Original file name without drive */
FILE *kf;
struct stat st;
time_t savtim[2]; /* save access & mod times here (sg) */
if (strcmp(fname, "-") == 0)
in = stdin;
else if ((in=fopen( fname, "rb"))==NULL) {
perror(fname);
return ERROR;
}
fstat(fileno(in), &st); /* Save mod time etc. */
switch (c=portgetw(in)) { /* Process header */
case KSQMAGIC:
Key = TRUE; break;
case SQMAGIC:
Key = FALSE; break;
default:
fprintf(stderr, "usq: %s is not a SQueezed file MAGIC= %x\n", fname, c);
fclose(in);
return(ERROR);
}
init_cr(); init_huff(); crc=0;
filecrc = portgetw(in); /* checksum */
if (Key) { /* Fetch key file to circular buffer */
for (i=PATHLEN-1,p=Keyname; --i>0; ) {
if ((*p++ = getc(in))==0)
break;
}
if ( !(kf=fopen(Keyname, "r"))) {
perror(Keyname);
fclose(in);
fprintf(stderr, "This key file is required for decryption.\n");
return ERROR;
}
i = fread(Keybuf, 1, KEYSIZE, kf);
if (i < 100) {
fclose(in);
printf("Bad key file or read error");
return ERROR;
}
Keyend = i + (Keyptr = Keybuf);
}
/* Get original file name to array */
for (i=PATHLEN,p = origname; --i>0; ) {
if ((*p++ = c = getc(in)) == 0)
break;
if (c == EOF) {
fprintf(stderr, "usq: premature EOF on %s\n", fname);
fclose(in); return(ERROR);
}
}
numnodes = portgetw(in);
if (numnodes < 0 || numnodes >= NUMVALS) {
fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
fclose(in); return(ERROR);
}
/* Initialize for possible empty tree (SPEOF only) */
Dnode[0]._children[0] = -(SPEOF + 1);
Dnode[0]._children[1] = -(SPEOF + 1);
for (i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
Dnode[i]._children[0] = portgetw(in);
Dnode[i]._children[1] = portgetw(in);
}
/* Get translated output bytes and write file */
if (MakeLCPathname && !IsAnyLower(origname))
uncaps(origname);
if (Fullpathname)
p = origname;
else
p = stem(origname);
if (Verbose || !inbackground)
fprintf(stderr, "usq: %s -> %s\n",fname, p);
if (out != stdout)
if ((out=fopen(p, "wb"))==NULL) {
perror(p);
fclose(in);
return ERROR;
}
while ((c = getcr()) != SPEOF) {
crc += c;
if ( c == '\r' && Nlmode)
continue;
putc(c, out);
}
fflush(out);
if (out != stdout) {
fclose(out);
#ifndef vax11c
savtim[0] = st.st_atime; /* Access time */
savtim[1] = st.st_mtime; /* Modification time */
utime(p, savtim);
#endif
}
if (ferror(in))
perror(fname);
else if (feof(in))
fprintf(stderr, "usq: premature EOF in %s\n", fname);
else if ( (crc - filecrc) & 0xFFFF ) {
fprintf(stderr, "usq: bad checksum in %s\n", fname);
} else {
fclose(in);
return(OK);
}
fclose(in);
return(ERROR);
}
/* initialize decoding functions *** from utr.c - */
init_cr()
{
Repct = 0;
}
init_huff()
{
Bpos = 99; /* force initial read */
}
/*
* Get bytes with decoding - this decodes repetition,
* calls getuhuff to decode file stream into byte
* level code with only repetition encoding.
*
* The code is simple passing through of bytes except
* that DLE is encoded as DLE-zero and other values
* repeated more than twice are encoded as value-DLE-count.
*/
getcr()
{
register c;
static value; /* current byte value or SPEOF */
if (Repct > 0) {
/* Expanding a repeated char */
--Repct; return(value);
} else {
/* Nothing unusual */
if ((c = getuhuff()) != DLE) {
/* It's not the special delimiter */
if ((value = c) == SPEOF)
Repct = LARGE;
return(value);
} else {
/* Special token */
if ((Repct = getuhuff()) == 0)
/* DLE, zero represents DLE */
return(DLE);
else {
/* Begin expanding repetition */
Repct -= 2; /* 2nd time */
return(value);
}
}
}
}
/* Decode file stream into a byte level code with only
* repetition encoding remaining.
*/
getuhuff()
{
register i;
static curin; /* last byte value read */
/* Follow bit stream in tree to a leaf*/
i = 0; /* Start at root of tree */
do {
if (++Bpos > 7) {
if ((curin = getc(in)) == EOF)
return(SPEOF);
if (Key) {
curin ^= *Keyptr;
if (++Keyptr >= Keyend)
Keyptr = Keybuf;
}
Bpos = 0;
/* move a level deeper in tree */
i = Dnode[i]._children[1 & curin];
} else
i = Dnode[i]._children[1 & (curin >>= 1)];
} while (POSITIVE(i));
NEG16TOINT(i)
/* Decode fake node index to original data value */
return (-(i + 1));
}
/*
* Machine independent getw which always gets bytes in the same order
* as the CP/M version of SQ wrote them
*/
portgetw(f)
FILE *f;
{
register c;
c = getc(f) & 0377;
return(c | ((getc(f)&0377) << 8));
}
/* make string s lower case */
uncaps(s)
register char *s;
{
for ( ; *s; ++s)
if (isupper(*s))
*s = tolower(*s);
}
/*
* IsAnyLower returns TRUE if string s has lower case letters.
*/
IsAnyLower(s)
register char *s;
{
for ( ; *s; ++s)
if (islower(*s))
return(TRUE);
return(FALSE);
}
/* Return pointer to file name part of pathname s */
char *
stem(s)
char *s;
{
register char *p;
for (p = s; *s; ) {
switch (*s++) {
case ':':
case '/':
case '\\':
p = s;
}
}
return p;
}